package mc2.ui;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;

public class FindDialog extends JDialog {

  private JTextField txtFind;
  private JButton btnFindNext;
  private JCheckBox chkMatchCase;
  private JRadioButton rbtnUp;
  private JButton btnMarkAll;
  private JCheckBox chkWholeWord;
  private JRadioButton rbtnDown;
  private JCheckBox chkWarp;
  private JButton btnClose;
  private ButtonGroup radioGroupUpDown;
  private final JTextArea textAreaToSearch;
  private int findPosition = 0;

  public FindDialog(JFrame parent, JTextArea textAreaToSearch) {
    super(parent);
    this.textAreaToSearch = textAreaToSearch;
    setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    setTitle("Find");
    Container pane = getContentPane();
    pane.setLayout(new GridBagLayout());

    GridBagConstraints c = new GridBagConstraints();

    c.insets = new Insets(2, 0, 0, 0);
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 1;
    c.weighty = 1;
    c.gridx = 0;
    c.gridy = 0;
    c.gridwidth = 1;
    pane.add(new JLabel("Find"), c);

    c.insets = new Insets(2, 0, 0, 0);
    c.weightx = 10;
    c.weighty = 1;
    c.gridx = 1;
    c.gridy = 0;
    c.gridwidth = 3;
    txtFind = new JTextField();
    pane.add(txtFind, c);

    c.insets = new Insets(2, 2, 2, 2);
    c.weightx = 1;
    c.weighty = 1;
    c.gridx = 4;
    c.gridy = 0;
    c.gridwidth = 1;
    btnFindNext = new JButton("Find Next");
    pane.add(btnFindNext, c);

    c.insets = new Insets(0, 0, 0, 0);
    c.weightx = 1;
    c.weighty = 1;
    c.gridx = 1;
    c.gridy = 1;
    c.gridwidth = 1;
    chkMatchCase = new JCheckBox("Match Case");
    pane.add(chkMatchCase, c);

    c.insets = new Insets(0, 0, 0, 0);
    c.weightx = 1;
    c.gridx = 2;
    c.gridy = 1;
    c.gridwidth = 1;
    rbtnUp = new JRadioButton("Up");
    pane.add(rbtnUp, c);

    c.insets = new Insets(2, 2, 2, 2);
    c.weightx = 1;
    c.gridx = 4;
    c.gridy = 1;
    c.gridwidth = 1;
    btnMarkAll = new JButton("Mark All");
    pane.add(btnMarkAll, c);

    c.insets = new Insets(0, 0, 0, 0);
    c.weightx = 1;
    c.weighty = 1;
    c.gridx = 1;
    c.gridy = 2;
    c.gridwidth = 1;
    chkWholeWord = new JCheckBox("Whole Word");
    pane.add(chkWholeWord, c);

    c.insets = new Insets(0, 0, 0, 0);
    c.weightx = 1;
    c.weighty = 1;
    c.gridx = 2;
    c.gridy = 2;
    c.gridwidth = 1;
    rbtnDown = new JRadioButton("Down");
    pane.add(rbtnDown, c);

    c.insets = new Insets(0, 0, 0, 0);
    c.weightx = 1;
    c.weighty = 1;
    c.gridx = 1;
    c.gridy = 3;
    c.gridwidth = 1;
    chkWarp = new JCheckBox("Wrap");
    pane.add(chkWarp, c);

    c.insets = new Insets(2, 2, 2, 2);
    c.weightx = 1;
    c.weighty = 1;
    c.gridx = 4;
    c.gridy = 3;
    c.gridwidth = 1;
    btnClose = new JButton("Close");
    pane.add(btnClose, c);

    radioGroupUpDown = new ButtonGroup();
    radioGroupUpDown.add(rbtnUp);
    radioGroupUpDown.add(rbtnDown);
    rbtnDown.setSelected(true);

    initListeners();

    pack();
    setSize(400, 120);
    setResizable(false);
    txtFind.requestFocus();
  }

  private void initListeners() {
    btnClose.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        setVisible(false);

      }
    });

    btnMarkAll.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        mark(txtFind.getText(), 0, true, false);

      }
    });

    btnFindNext.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {

        findPosition = mark(txtFind.getText(), findPosition, false, rbtnUp.isSelected());

      }
    });

    addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent e) {
        setVisible(false);
      }
    });

  }

  // Removes only our private highlights
  public void removeHighlights(Class<? extends DefaultHighlightPainter> clazz) {
    Highlighter hilite = textAreaToSearch.getHighlighter();
    Highlighter.Highlight[] hilites = hilite.getHighlights();

    for (int i = 0; i < hilites.length; i++) {
      if (clazz.isAssignableFrom((hilites[i].getPainter().getClass()))) {
        hilite.removeHighlight(hilites[i]);
      }
    }
  }
  
  private int getNextPos(String text, String pattern, final int posOriginal, boolean back) {
    int pos = posOriginal;
    if (back) {
      text = text.substring(0, Math.max(0, Math.min(text.length(), pos - pattern.length())));
    }
    pos = back ? text.lastIndexOf(pattern) : text.indexOf(pattern, pos);
    return pos;
  }
  
  @Override
  public void setVisible(boolean b) {
    // TODO Auto-generated method stub
    super.setVisible(b);
    findPosition = 0;
    
  }

  // Creates highlights around all occurrences of pattern in textComp
  public int mark(String pattern, final int posOriginal, boolean highligt, boolean back) {
    // First remove all old highlights
    int pos = posOriginal;

     if(highligt) {
       removeHighlights(MyHighlightPainter.class);
       removeHighlights(MyHighlightPainterFind.class);
     }


    if (pattern == null || pattern.trim().isEmpty()) {
      return pos;
    }
    
    final String textOriginal = textAreaToSearch.getText();
    
    try {
      Highlighter hilite = textAreaToSearch.getHighlighter();
      
      String text = textOriginal;
     
      boolean run = true;
      // Search for pattern
      while (run && (pos = getNextPos(text, pattern, pos, back)) >= 0) {

        // Create highlighter using private painter and apply around pattern

        if (highligt) {
          hilite.addHighlight(pos, pos + pattern.length(), myHighlightPainter);
        } else {
          removeHighlights(MyHighlightPainter.class);
          removeHighlights(MyHighlightPainterFind.class);
          hilite.addHighlight(pos, pos + pattern.length(), myHighlightPainterFind);
        }

        if (!back) {
          pos += pattern.length();
        }
        run = highligt;
      }
    } catch (BadLocationException e) {
    }
    

    return pos;
  }

  // An instance of the private subclass of the default highlight painter
  Highlighter.HighlightPainter myHighlightPainter = new MyHighlightPainter(Color.YELLOW);
  Highlighter.HighlightPainter myHighlightPainterFind = new MyHighlightPainterFind(Color.PINK);

  // A private subclass of the default highlight painter
  class MyHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter {
    public MyHighlightPainter(Color color) {
      super(color);
    }
  }

  // A private subclass of the default highlight painter
  class MyHighlightPainterFind extends DefaultHighlighter.DefaultHighlightPainter {
    public MyHighlightPainterFind(Color color) {
      super(color);
    }
  }
  
  public static void main(String[] args) {
    System.out.println("Hallo".substring(0, 0));
  }
}
